/*
    SEL - Simple DirectMedia Layer Extension Library
    Copyright (C) 2001 Matej Knopp <knopp@users.sf.net>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#ifndef __sel_event_h__
#define __sel_event_h__

#include "sdl.h"

namespace SEL
{

class EventHandler;

//! The general event class.
/*!
  This class stores any type of SDL event. An event is generated on an user
  action (like mouse motion, keypress, activation/deactivation of the window,
  etc.) There are two possible ways of handling events. The first is similiar
  to the one of SDL:
  \code
  SEL::Event event;
  while (1) // the main loop
  {
  	if (event.poll ()) // Check if we have any event in the queue, and
			   // if yes, store the event in the `event' object.
	{
		switch event.type ()
		{
			case SDL::MOUSE_MOTION:
				// do something here
				break;
			case SDL::QUIT: // the user requested quit
				SEL::quit ();
				exit (0);
				break;
			...
		}
	}
  }
  \endcode
  The other way is more elegant, but is rather different to the event
  handling of SDL.
  \code
  // derive a new class, and reimplement the events we are interested in
  class MyEventHandler : public SEL::EventHandler
  {
  	virtual bool handleKeyPressEvent (SDL::keysym &keysym);
  };

  virtual bool
  MyEventHandler::handleKeyPressEvent (SDL::keysym &keysym)
  {
  	// do something here...
	return true;
  }

  ...
  MyEventHandler myhandler;
  while (1) // the main loop
  {
  	SEL::Event::handleEvents (myhandler);
  }
  \endcode
  If you don't want to use events to determine the state of the
  input devices, you can use the SEL::Keyboard, SEL::Joystick and
  SEL::Mouse classes directly.
 */
class Event
{
public:
	//! Create an empty event.
	Event ()				{ }

	//! Default destructor (empty).
	~Event ()				{ }

	//! Get the result of the polling methods.
	/*!
	  The SDL::Event is an union that contains all possible
	  event types. For more information about SDL::Event consult
	  the SDL documentation.
	  \sa poll (), wait ()
	 */
	// this can't be constant...
	SDL::Event &event ()			{ return m_event; }

	//! Get the type of stored event.
	/*!
	  the type can be one of these:
	  \code
	enum { SDL::NOEVENT = 0,	// Unused (do not remove)
	       SDL::ACTIVEEVENT,	// Application loses/gains visibility
	       SDL::KEYDOWN,		// Keys pressed
	       SDL::KEYUP,		// Keys released
	       SDL::MOUSEMOTION,	// Mouse moved
	       SDL::MOUSEBUTTONDOWN,	// Mouse button pressed
	       SDL::MOUSEBUTTONUP,	// Mouse button released
	       SDL::JOYAXISMOTION,	// Joystick axis motion
	       SDL::JOYBALLMOTION,	// Joystick trackball motion
	       SDL::JOYHATMOTION,	// Joystick hat position change
	       SDL::JOYBUTTONDOWN,	// Joystick button pressed
	       SDL::JOYBUTTONUP,	// Joystick button released
	       SDL::QUIT,		// User-requested quit
	       SDL::SYSWMEVENT,		// System specific event
	       SDL::EVENT_RESERVEDA,	// Reserved for future use..
	       SDL::EVENT_RESERVEDB,	// Reserved for future use..
	       SDL::VIDEORESIZE,	// User resized video mode
	       SDL::VIDEOEXPOSE,	// Screen needs to be redrawn
	       SDL::EVENT_RESERVED2,	// Reserved for future use..
	       SDL::EVENT_RESERVED3,	// Reserved for future use..
	       SDL::EVENT_RESERVED4,	// Reserved for future use..
	       SDL::EVENT_RESERVED5,	// Reserved for future use..
	       SDL::EVENT_RESERVED6,	// Reserved for future use..
	       SDL::EVENT_RESERVED7,	// Reserved for future use..
	       // Events SDL::USEREVENT through SDL::MAXEVENTS-1 are for your use
	       SDL::USEREVENT = 24,
	       // This last event is only for bounding internal arrays
	       // It is the number of bits in the event mask datatype -- Uint32
	      SDL::NUMEVENTS = 32
	};
	  \endcode
	 */
	Uint8 type () const			{ return m_event.type; }

	//! Set the value of an SEL::Event to that of an existing SDL::Event.
	Event &operator= (const SDL::Event &event);

	//! Poll for currently pending event.
	/*!
	  If there is any pending event, it will be removed from the queue,
	  and (if \a fetch is true) stored in this class instance.
	  \param fetch - if false only polls for pending event but don't store
	  it.
	  \return true if any events were pending.
	  \sa wait (), handleEvents ()
	 */
	bool poll (bool fetch = true);

	//! Wait for the next available event.
	/*!
	  This function waits for the next available event, and (if \a fetch
	  is true) stores it in this class instance.
	  \param fetch - if false, the event (once available) is not stored,
	  		 only removed from the queue.
	  \return true - when an event became available, or false if something
	  		 went wrong.
	  \sa poll (), handleEvents ()
	  */
	bool wait (bool fetch = true);

	//! Add an event to the event queue.
	/*!
	  \note Pushing device input events doesn't modify the state of
	  device withing SDL.
	  \warning Don't forget to initialize the event before pushing.
	  \return true on success, false if the event couldn't be pushed.
	  If the event queue is full, this function fails.
	  */
	bool push ();

	//! Pump the event loop, gathering events from the input devices.
	/*!
	  This function updates the event queue and internal device state.
	  \warning This should only be run in the thread that sets the video
	  mode.
	 */
	static void pumpEvents ();

	//! Set up a filter to process all events before they change
	//! internal state and are posted the the internal event queue.
	/*!
	  If the filter returns 1, then the event will be added to the
	  internal queue. If it returns 0, then the event will be dropped
	  from the queue, but the internal state will still be updated.
	  This allows selective filtering of dynamically ariving events.
	  \warning Be very careful of what you do in the event filter
	  function, as it may run in a different thread!

          There is one caveat when dealing with the SDL::QUITEVENT event type.
	  The event filter is only called when the window manager desires to
	  close the application window. If the event filter returns 1, then
	  the window will be closed, otherwise the window will remain open
	  if possible. If the quit event is generated by an interrupt signal,
	  it will bypass the internal queue and be delivered to the application
	  at the next event poll.
	  \param filter the function you want to use for filtering
	 */
	static void setEventFilter (SDL::EventFilter filter);

	//! Return current event filter.
	/*!
	  This can be used to "chain" filters. If there is no filter
	  set, this function returns NULL.
	 */
	static SDL::EventFilter eventFilter ();

	//! Set the state of processing certain events.
	/*!
	  If \a state is set to SDL::IGNORE, that event will be
	  automatically dropped from the event queue and will not even
	  be filtered.

	  If \a state is set to SDL::ENABLE, that event will be
	  processed normally.

	  If \a state is set to SDL::QUERY, this function will return
	  the current processing of the specified state.

	  A list of event types can be found in the SDL::Event section
	  in the SDL documentation.

	  \param type the event type
	  \param state the state you want to set as documented above
	  \returns the current processing state for the specified event \a type
	 */
	static Uint8 eventState (Uint8 type, int state);

	//! Handle all queued events using the specified EventHandler
	/*!
	  This function polls for active events and calls the event
	  callback methods. To actually handle any events, you need to
	  create a derivate of the EventHandler class reimplementing the
	  callbacks for the events you're interested in. See the
	  EventHandler documentation for more details.
	  \param handler the EventHandler which should handle the events.
	  \sa EventHandler
	 */
	static void handleEvents (EventHandler &handler);

protected:
	//! This is where the event is stored.
	/*!
	  To access this field use the event () member function.
	  \sa event ()
	 */
	SDL::Event m_event;
};

//////////////////////////////////////////////////////////////////////
//    This is shamelessly taken from the SDLmm SDL wrapper.         //
//    You can found SDLmm here: http://sdlmm.sourceforge.net        //
//    SDLmm is copyright (c) 2001 David Hedbor <david@hedbor.org>   //
//////////////////////////////////////////////////////////////////////

//! The base class used for custom Event handlers.
/*!
  The event handling in SEL is rather different to that of SDL in
  that it uses classes derived from the EventHandler. This allows
  for clean, type-safe code much closer to the spirit of C++ than the use
  of a union with a type field. To handle one or more events, you simply
  build a class derived from this, reimplementing the only functions for
  the events you need to handle.

  See the SEL::Event class documentation for the example of using an EventHandler.
  \sa Event::handleEvents()
  \author The original author of this class is David Hedbor <david@hedbor.org>
*/
class EventHandler
{
public:
	//! \name Keyboard events
	//@{

	//! Keyboard event callback.
	/*!
	  This callback is used when an event of type SDL::KEYDOWN or SDL::KEYUP is
	  reported. These occur when keys are pressed or released.

	  \note Repeating SDL::KEYDOWN events will occur, if key repeat is
	  enabled (see EnableKeyRepeat()).
	  \note This function is only called, if the default HandleKeyPressEvent()
	  and / or HandleKeyReleaseEvent() methods are used.
	  \param keysym information about the pressed key
	  \param pressed true for SDL::KEYDOWN, false for SDL::KEYUP

	  \return true if the event was handled, false if it was not. If
	  the event wasn't handled, it will be handed over to the generic
	  handleEvent() method.
	*/
	virtual bool handleKeyboardEvent (SDL::keysym &keysym, bool pressed)
	{
		return false;
	}

	//! Keyboard press event callback.
	/*!
	  This callback is used when an event of type SDL::KEYDOWN is
	  reported. A keyboard press event occurs when a key is pressed.

	  \note Repeating SDL::KEYDOWN events will occur, if key repeat is
	  enabled (see EnableKeyRepeat()).
	  \note The default declaration of this method calls the
	  HandleKeyboardEvent() method. If you want to handle both key
	  presses and key releases in the same method, just redefine
	  HandleKeyboardEvent().
	  \param keysym information about the pressed key

	  \return true if the event was handled, false if it was not. If
	  the event wasn't handled, it will be handed over to the generic
	  handleEvent() method.
	 */
	virtual bool handleKeyPressEvent (SDL::keysym &keysym)
	{
		return handleKeyboardEvent (keysym, true);
	}

	//! Keyboard release event callback.
	/*!
	  This callback is used when an event of type SDL::KEYUP is
	  reported. A keyboard press event occurs when a key is released.

	  \param keysym the information about the released key
	  \note The default declaration of this method calls the
	  HandleKeyboardEvent() method. If you want to handle both key
	  presses and releases in the same method, just redefine
	  HandleKeyboardEvent().

	  \return true if the event was handled, false if it was not. If
	  the event wasn't handled, it will be handed over to the generic
	  handleEvent() method.
	 */
	virtual bool handleKeyReleaseEvent (SDL::keysym &keysym)
	{
		return handleKeyboardEvent (keysym, false);
	}
	//@}

	//! \name Mouse events
	//@{

	//! Mouse motion event callback.
	/*!
	  This is used when an event of type SDL::MOUSEMOTION is reported.

	  Simply put, a SDL::MOUSEMOTION type event occurs when a user
	  moves the mouse within the application window or when
	  SDL::WarpMouse is called. Both the absolute (\a x and \a y) and
	  relative (\a xrel and \a yrel) coordinates are reported along with the
	  current button states (\a state). The button \a state can be
	  interpreted using the SDL::BUTTON macro (see GetMouseState()).

	  If the cursor is hidden (Display::HideCursor()) and the input is
	  grabbed (Display::GrabInput(SDL::GRAB_ON)), then the mouse will
	  give relative motion events even when the cursor reaches the
	  edge of the screen. This is currently only implemented on
	  Windows and Linux/Unix-a-likes.

	  \param state the current button state.
	  \param x, y the absolute x/y coordinates of the mouse pointer
	  \param xrel, yrel relative motion in the x/y directions

	  \return true if the event was handled, false if it was not. If
	  the event wasn't handled, it will be handed over to the generic
	  handleEvent() method.
	 */
	virtual bool handleMouseMotionEvent (Uint8 state, Uint16 x, Uint16 y,
					     Sint16 xrel, Sint16 yrel)
	{
		return false;
	}

	//! Mouse button event callback.
	/*!
	  This is used when an event of type SDL::MOUSEBUTTONDOWN or
	  SDL::MOUSEBUTTONUP is reported.

	  When a mouse button press is detected the number of the button
	  pressed (from 1 to 255, with 1 usually being the left button and
	  2 the right) is placed into \a button. The position of the mouse
	  when this event occured is stored in \a x and \a y.

	  \note This function is only called, if the default
	  HandleMouseButtonPressEvent() and / or
	  HandleMouseButtonReleaseEvent() methods are used.

	  \param button the mouse button index
	  \param x, y the x/y coordinates of the mouse at press time
	  \param pressed true for SDL::MOUSEBUTTONDOWN, false for
	  SDL::MOUSEBUTTONUP.

	  \return true if the event was handled, false if it was not. If
	  the event wasn't handled, it will be handed over to the generic
	  handleEvent() method.
	 */
	virtual bool handleMouseButtonEvent (Uint8 button, Uint16 x, Uint16 y,
					     bool pressed)
	{
		return false;
	}

	//! Mouse button press event callback.
	/*!
	  This is used when an event of type SDL::MOUSEBUTTONDOWN is reported.

	  When a mouse button press is detected the number of the button
	  pressed (from 1 to 255, with 1 usually being the left button and
	  2 the right) is placed into \a button. The position of the mouse
	  when this event occured is stored in \a x and \a y.

	  \note The default declaration of this method calls the
	  HandleMouseButtonEvent() method. If you want to handle both
	  button presses and releases in the same method, just redefine
	  HandleMouseButtonEvent().

	  \param button the mouse button index
	  \param x, y the x/y coordinates of the mouse at press time

	  \return true if the event was handled, false if it was not. If
	  the event wasn't handled, it will be handed over to the generic
	  handleEvent() method.
	 */
	virtual bool handleMouseButtonPressEvent (Uint8 button, Uint16 x,
						  Uint16 y)
	{
		return handleMouseButtonEvent (button, x, y, true);
	}

	//! Mouse button release event callback.
	/*!
	  This is used when an event of type SDL::MOUSEBUTTONUP is reported.

	  When a mouse button release is detected the number of the button
	  release (from 1 to 255, with 1 usually being the left button and
	  2 the right) is placed into \a button. The position of the mouse
	  when this event occured is stored in \a x and \a y.

	  \note The default declaration of this method calls the
	  HandleMouseButtonEvent() method. If you want to handle both
	  button presses and releases in the same method, just redefine
	  HandleMouseButtonEvent().

	  \param button the mouse button index
	  \param x, y the x/y coordinates of the mouse at press time

	  \return true if the event was handled, false if it was not. If
	  the event wasn't handled, it will be handed over to the generic
	  handleEvent() method.
	 */
	virtual bool handleMouseButtonReleaseEvent (Uint8 button, Uint16 x,
						    Uint16 y)
	{
		return handleMouseButtonEvent (button, x, y, false);
	}
	//@}

	//! \name Joystick events
	//@{

	//! Joystick axis motion event callback.
	/*!
	  This is used when an event of type SDL::JOYAXISMOTION is reported.

	  A SDL::JOYAXISMOTION event occurs when ever a user moves an axis
	  on the joystick.
	  \param joystick the index of the joystick that reported the event
	  \param axis the index of the axis (for a more detailed explaination
	  see the Joystick section of the SDL  manual).
	  \params value is the current position of the axis.

	  \return true if the event was handled, false if it was not. If
	  the event wasn't handled, it will be handed over to the generic
	  handleEvent() method.
	 */
	virtual bool handleJoyAxisEvent (Uint8 joystick, Uint8 axis,
					 Sint16 value)
	{
		return false;
	}

	//! Joystick button event callback.
	/*!
	  This is used when an event of type SDL::JOYBUTTONDOWN or
	  SDL::JOYBUTTONUP is reported.

	  These events occurs when ever a user presses or releases a
	  button on a joystick.

	  \note This function is only called if the default
	  HandleJoyButtonPressEvent() and / or
	  HandleJoyButtonReleaseEvent() methods are used.

	  \param joystick the index of the joystick that reported the event
	  \param button the index of the pressed button (for a more
	  detailed explaination see the Joystick section of the SDL
	  manual).
	  \param pressed true for SDL::JOYBUTTONDOWN, false for SDL::JOYBUTTONUP.

	  \return true if the event was handled, false if it was not. If
	  the event wasn't handled, it will be handed over to the generic
	  handleEvent() method.
	*/
	virtual bool handleJoyButtonEvent (Uint8 joystick, Uint8 button,
					   bool pressed)
	{
		return false;
	}

	//! Joystick button press event callback.
	/*!
	  This is used when an event of type SDL::JOYBUTTONDOWN is reported.

	  A SDL::JOYBUTTONDOWN event occurs when ever a user presses a
	  button on a joystick.

	  \note The default declaration of this method calls the
	  HandleJoyButtonEvent() method. If you want to handle both
	  button presses and releases in the same method, just redefine
	  HandleJoyButtonEvent().

	  \param joystick the index of the joystick that reported the event
	  \param button the index of the pressed button (for a more
	  detailed explaination see the Joystick section of the SDL
	  manual).

	  \return true if the event was handled, false if it was not. If
	  the event wasn't handled, it will be handed over to the generic
	  handleEvent() method.
	*/
	virtual bool handleJoyButtonPressEvent (Uint8 joystick, Uint8 button)
	{
		return handleJoyButtonEvent (joystick, button, true);
	}

	//! Joystick button release event callback.
	/*!
	  This is used when an event of type SDL::JOYBUTTONUP is reported.

	  A SDL::JOYBUTTONUP event occurs when ever a user releases a
	  button on a joystick.

	  \note The default declaration of this method calls the
	  HandleJoyButtonEvent() method. If you want to handle both
	  button presses and releases in the same method, just redefine
	  HandleJoyButtonEvent().

	  \param joystick the index of the joystick that reported the event
	  \param button the index of the released button (for a more
	  detailed explaination see the Joystick section of the SDL
	  manual).

	  \return true if the event was handled, false if it was not. If
	  the event wasn't handled, it will be handed over to the generic
	  handleEvent() method.
	 */
	virtual bool handleJoyButtonReleaseEvent (Uint8 joystick, Uint8 button)
	{
		return handleJoyButtonEvent (joystick, button, false);
	}

	//! Joystick hat position change event callback.
	/*!
	  This is used when an event of type SDL::JOYHATMOTION is reported.

	  A SDL::JOYHATMOTION event occurs when ever a user moves a hat on
	  the joystick. The field \a joystick is the index of the joystick
	  that reported the event and \a hat is the index of the hat (for
	  a more detailed exlaination see the Joystick section in the SDL
	  documentation). \a value is the current position of the hat. It is
	  a logically OR'd combination of the following values (whose
	  meanings should be pretty obvious):
	  - SDL::HAT_CENTERED
	  - SDL::HAT_UP
	  - SDL::HAT_RIGHT
	  - SDL::HAT_DOWN
	  - SDL::HAT_LEFT

	  The following defines are also provided:

	  - SDL::HAT_RIGHTUP
	  - SDL::HAT_RIGHTDOWN
	  - SDL::HAT_LEFTUP
	  - SDL::HAT_LEFTDOWN

	  \param joystick joystick device index
	  \param hat joystick hat index
	  \param value hat position

	  \return true if the event was handled, false if it was not. If
	  the event wasn't handled, it will be handed over to the generic
	  handleEvent() method.
	 */
	virtual bool handleJoyHatEvent (Uint8 joystick, Uint8 hat, Uint8 value)
	{
		return false;
	}

	//! Joystick trackball motion event callback.
	/*!
	  This is is used when an event of type SDL::JOYBALLMOTION is reported.

	  A SDL::JOYBALLMOTION event occurs when a user moves a trackball
	  on the joystick. The field \a joystick is the index of the
	  joystick that reported the event and \a ball is the index of the
	  trackball (for a more detailed explaination see the Joystick
	  section in the SDL documentation). Trackballs only return
	  relative motion, this is the change in position on the ball
	  since it was last polled (last cycle of the event loop) and it
	  is stored in \a xrel and \a yrel.

	  \param joystick joystick device index
	  \param ball joystick trackbal index
	  \param xrel, yrel relative motion in the x/y directions

	  \return true if the event was handled, false if it was not. If
	  the event wasn't handled, it will be handed over to the generic
	  handleEvent() method.
	 */
	virtual bool handleJoyBallEvent (Uint8 joystick, Uint8 ball,
					 Sint16 xrel, Sint16 yrel)
	{
		return false;
	}
	//@}

	//! \name Window and display events
	//@{

	//! Application visibility event callback.
	/*!
	  This callback is called when an event of type SDL::ACTIVEEVENT is
	  reported.

	  When the mouse leaves or enters the window area a
	  SDL::APPMOUSEFOCUS type activation event occurs, if the mouse
	  entered the window then \a gain will be true, otherwise \a gain
	  will be false. A SDL::APPINPUTFOCUS type activation event occurs
	  when the application loses or gains keyboard focus. This usually
	  occurs when another application is made active. Finally, a
	  SDL::APPACTIVE \a type event occurs when the application is
	  either minimised/iconified (\a gain=false) or restored.

	  \param gain false if the event is a loss or true if it's a gain
	  \param state SDL::APPMOUSEFOCUS if mouse focus was gained or
	  lost, SDL::APPINPUTFOCUS if input focus was gained or lost, or
	  SDL::APPACTIVE if the application was iconified (\a gain=false) or
	  restored (\a gain=true)

	  \return true if the event was handled, false if it was not. If
	  the event wasn't handled, it will be handed over to the generic
	  handleEvent() method.
	 */
	virtual bool handleActiveEvent (bool gain, Uint8 state)
	{
		return false;
	}

	//! Window resize event callback.
	/*!
	  This is used when an event of type SDL::VIDEORESIZE is reported.

	  When SDL::RESIZABLE is passed as a flag to
	  Display::SetVideoMode() the user is allowed to resize the
	  applications window. When the window is resized an
	  SDL::VIDEORESIZE is reported, with the new window width and
	  height values stored in \a w and \a h, respectively. When an
	  SDL::VIDEORESIZE is recieved the window should be resized to the
	  new dimensions using Display::SetVideoMode();

	  \param w, h new width and height of the window.

	  \return true if the event was handled, false if it was not. If
	  the event wasn't handled, it will be handed over to the generic
	  handleEvent() method.
	 */
	virtual bool handleResizeEvent (int w, int h)
	{
		return false;
	}

	//! Platform-dependent window manager event callback.
	/*!
	  The system window manager event contains a pointer to
	  system-specific information about unknown window manager
	  events. If you enable this event using Event::EventState(), it will
	  be generated whenever unhandled events are received from the
	  window manager. This can be used, for example, to implement
	  cut-and-paste in your application.

	  If you want to obtain system-specific information about the
	  window manager, you can fill the version member of a
	  SDL_SysWMinfo structure (details can be found in SDL_syswm.h,
	  which must be included) using the SDL_VERSION() macro found in
	  SDL_version.h, and pass it to the function:

	  \code
	  int SDL_GetWMInfo(SDL_SysWMinfo *info);
	  \endcode

	  \return true if the event was handled, false if it was not. If
	  the event wasn't handled, it will be handed over to the generic
	  handleEvent() method.
	 */
	virtual bool handleSysWMEvent ()
	{
		return false;
	}
	//@}

	//! \name Other events
	//@{

	//! Callback for user-defined events.
	/*!
	  This event is unique - it is never created by SDL but only by
	  the user. The event can be pushed onto the event queue using
	  Event::Push(). The contents of \a data1 and \a data2 are
	  completely up to the programmer. The only requirement is that
	  \a type is a value from SDL::USEREVENT to SDL::NUMEVENTS-1
	  (inclusive).

	  \param type SDL::USEREVENT through to SDL::NUMEVENTS-1
	  \param code user defined event code
	  \param data1, data2 user defined data pointers

	  \return true if the event was handled, false if it was not. If
	  the event wasn't handled, it will be handed over to the generic
	  handleEvent() method.
	 */
	virtual bool handleUserEvent (Uint8 type, int code,
				      void *data1, void *data2)
	{
		return false;
	}

	//! Quit requested event callback.
	/*!
	  This is used whan an event of type SDL::QUIT is reported.

	  The SDL::QUIT event is very important. If you filter out or
	  ignore a quit event it is impossible for the user to close the
	  window. On the other hand, if you do accept a quit event, the
	  application window will be closed, and screen updates will still
	  report success, even though the application will no longer be
	  visible.

	  \note The macro SDL::QuitRequested will return non-zero if a
	  quit event is pending.

	  \return true if the event was handled, false if it was not. If
	  the event wasn't handled, it will be handed over to the generic
	  handleEvent() method.
	 */
	virtual bool handleQuitEvent ()
	{
		return false;
	}
	//@}

	//! \name Catch-all event handler
	//@{

	//! Catch-all event handler
	/*!
	  This method is called if none of the event specific callbacks
	  handled event (i.e they returned false).

	  \note It's both easier and more efficient to use the
	  event-specific callbacks, so unless you really want to do all
	  the work yourself, you want to use those.

	  \param event the current event

	  \return true if the event was handled, false if it was not
	 */
	virtual bool handleEvent (SDL::Event &event)
	{
		return false;
	}
	//@}
};

//////////////////////////////////////////////////////////////////
//////////////////////// INLINE FUNCTIONS ////////////////////////
//////////////////////////////////////////////////////////////////

inline Event &
Event::operator= (const SDL::Event &event)
{
	m_event = event;
	return *this;
}

inline bool
Event::poll (bool fetch)
{
	if (fetch)
		return SDL::PollEvent (&m_event);
	else
		return SDL::PollEvent (NULL);
}

inline bool
Event::wait (bool fetch)
{
	if (fetch)
		return SDL::WaitEvent (&m_event);
	else
		return SDL::WaitEvent (NULL);
}

inline bool
Event::push ()
{
	return SDL::PushEvent (&m_event) == 0;
}

inline void
Event::pumpEvents ()
{
	SDL::PumpEvents ();
}

inline void
Event::setEventFilter (SDL::EventFilter filter)
{
	SDL::SetEventFilter (filter);
}

inline SDL::EventFilter
Event::eventFilter ()
{
	return SDL::GetEventFilter ();
}

inline Uint8
Event::eventState (Uint8 type, int state)
{
	return SDL::EventState (type, state);
}

} // namespace SEL

#endif // __sel_event_h__
